﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Net;

namespace Frw.Protocols.Communications.Tcp
{
    public class TCPServer : IDisposable
    {
        //private int _port = 7734;
        //private string _ipaddress = "127.0.0.1";
        bool disposed = false;

        public delegate void onDataRecieved(String data);
        public event onDataRecieved dataRecieved;
        public string _result = "";

        public string IPAddress { get; set; }
        public int Port { get; set; }

        Thread client = null;
        TcpListener t = null;

        public TCPServer(int port, string ip)
        {
            if (port > 0)
            {
                this.Port = port;
                this.IPAddress = ip;
            }
        }

        ManualResetEvent writeDone = new ManualResetEvent(false);
        private void onConnect(object c)
        {
            try
            {
                System.Net.Sockets.TcpClient s = (System.Net.Sockets.TcpClient)c;
                //Read
                NetworkStream stream = s.GetStream();
                if (stream.CanRead)
                {
                    byte[] buffer = new byte[s.ReceiveBufferSize];
                    stream.Read(buffer, 0, buffer.Length);
                    _result = Encoding.ASCII.GetString(buffer);
                }

                //Response
                if (stream.CanWrite)
                {
                    byte[] status = Encoding.ASCII.GetBytes("ACK: Ok");
                    stream.BeginWrite(status, 0, status.Length, new AsyncCallback(writeCallback), stream);
                    writeDone.WaitOne();
                }
                stream.Close();
                stream.Dispose();
                s.Close();

                this.dataRecieved(_result + "\r\n");
            }
            catch (Exception err)
            {
                Console.WriteLine(err.Message);
            }
        }
        private void writeCallback(IAsyncResult ar)
        {
            try
            {
                NetworkStream stream = (NetworkStream)ar.AsyncState;
                stream.EndWrite(ar);
                writeDone.Set();
            }
            catch (Exception err)
            {
                Console.WriteLine(err.Message);
            }
        }

        public void startServer()
        {
            try
            {
                IPAddress ip = System.Net.IPAddress.Parse(IPAddress);
                IPEndPoint end = new IPEndPoint(ip, Port);

                t = new TcpListener(end);
                t.Start();
                while (true)
                {
                    client = new Thread(new ParameterizedThreadStart(onConnect));
                    System.Net.Sockets.TcpClient tcp = t.AcceptTcpClient();
                    client.Start(tcp);
                }
            }
            catch (Exception err)
            {
                Console.WriteLine(err.Message);
            }
        }

        #region IDisposable Members

        public void Dispose()
        {
            if (t != null)
            {
                t.Stop();
            }

            if (client != null)
            {
                client.Abort();
                client = null;
            }

            this.disposed = true;
        }

        #endregion
    }
}
